<!---
  @author: andy
  @description: 标签栏组件
-->
<template>
  <div class="layout-tabbar" :style="{height : `${config.tabbar.height}px` , ...tabbarStyle}">
    <div class="layout-tabbar-inner">
      <span @click="onClickLeft" class="arrow-left-icon-button">
        <LeftOutlined class="arrow-icon" />
      </span>
      <div class="tabbar-box" @wheel.passive="onMouseWheel">
        <VueDraggable v-if="config.tabbar.draggable" v-model="currentTabs" class="draggable-box" target=".tabbar-transition" @update="onUpdate">
          <TransitionGroup type="transition" class="tabbar-transition" tag="div" name="slide">
            <div class="tabbar-item" :class="{active : item.fullPath === $route.fullPath , [config.tabbar.style] : true}" @click="onClickTab($event , item)" :data-index="index" v-for="(item , index) in currentTabs" :key="item.name">
              <img v-if="config.tabbar.showIcon && item.meta.icon" class="tabbar-icon" :src="(item.meta.icon as string)" />
              <span>{{item.meta.title}}</span>
              <PushpinOutlined v-if="item.meta.fixed" class="tabbar-close-icon" />
              <CloseOutlined @click.stop="onCloseTab(item)" v-else class="tabbar-close-icon" />
            </div>
          </TransitionGroup>
        </VueDraggable>
        <div v-else class="tabbar-item" :class="{active : item.fullPath === $route.fullPath , [config.tabbar.style] : true}" @click="onClickTab($event , item)" :data-index="index" v-for="(item , index) in currentTabs" :key="item.name">
          <img v-if="config.tabbar.showIcon && item.meta.icon" class="tabbar-icon" :src="(item.meta.icon as string)" />
          <span>{{item.meta.title}}</span>
          <PushpinOutlined v-if="item.meta.fixed" class="tabbar-close-icon" />
          <CloseOutlined @click.stop="onCloseTab(item)" v-else class="tabbar-close-icon" />
        </div>
      </div>
      <span @click="onClickRight" class="arrow-right-icon-button">
        <RightOutlined class="arrow-icon" />
      </span>
      <span @click="onReload" class="arrow-right-icon-button">
        <ReloadOutlined />
      </span>
      <TabbarTool 
        v-if="config.tabbar.showMore"
        @max-screen="onMaxScreen"
        @reload="onReload"
        @fixed="onFixed"
      />
      <span v-if="config.tabbar.showFullscreen" @click="onMaxScreen" class="arrow-right-icon-button">
        <component :is="!isFullscreen ? FullscreenOutlined : FullscreenExitOutlined" class="fullscreen-icon" />
      </span>
    </div>
  </div>
</template>
<script lang='ts' setup>
import { LeftOutlined , RightOutlined , CloseOutlined , PushpinOutlined , ReloadOutlined , FullscreenOutlined , FullscreenExitOutlined } from '@ant-design/icons-vue';
import { useTabbar } from './tabbar/useTabbar';
import { VueDraggable, type SortableEvent } from 'vue-draggable-plus';
import type { RouteLocationNormalized } from 'vue-router';
import { useRoute } from 'vue-router';
import TabbarTool from './TabbarTool.vue';
import { computed, nextTick, onMounted, watch, type CSSProperties } from 'vue';
import { useConfigStore } from '@/stores/configs/config';
import { storeToRefs } from 'pinia';
import { useAccessStore } from '@/stores/access/access'; 
import { getPathByKey } from '@/utils/tree';
type Props = {
  sidebarWidth: number;
}
const props = defineProps<Props>();
let tabbarWidth = 0;
const accessStore = useAccessStore();
const configStore = useConfigStore();
const { config } = storeToRefs(configStore);
const route = useRoute();
const emits = defineEmits(['toggle-fullscreen' , 'reload' , 'fixed']);
const { currentTabs , clickTab , closeAndOpenNextTab , updateTab , updateTabMeta } = useTabbar();
const isFullscreen = computed(() => {
  const { header , sidebar } = config.value;
  return !!(header.hidden && sidebar.hidden);
});
const tabbarStyle = computed(() => {
  let css: CSSProperties = {};
  const layout = config.value.app.layout;
  if (layout === 'mixed-nav') {
    if (accessStore.mixedSidebarMenus.length === 0) {
      css = {}
    } else {
      css = {
        width : `calc(100% - ${props.sidebarWidth}px)`,
        marginLeft : `${props.sidebarWidth}px`
      }
    }
  } else if (layout === 'header-nav') {
    css = {
      width : '100%',
      marginLeft : '0px'
    }
  } else if (layout === 'header-sidebar-nav') {
    css = {
      width : `calc(100% - ${props.sidebarWidth}px)`,
      marginLeft : `${props.sidebarWidth}px`
    }
  } else if (layout === 'sidebar-nav') {
    css = {}
  }
  return css;
})
const onClickTab = (evt: MouseEvent , tab: RouteLocationNormalized) => {
  clickTab(tab);
  const dom = evt.currentTarget as HTMLElement;
  if (dom) {
    startMove(dom);
  }
  const pathList = getPathByKey(tab.meta.code as string , accessStore.accessMenus , {keyProp : 'code'});
  if (configStore.config.secondMenu.enable) {
    if (pathList.length > 1) {
      const code = pathList[0].code;
      accessStore.setSecondMenusByCode(code);
    }
  } else {
    if (pathList.length > 0) {
      const code = pathList[0].code;
      accessStore.setMixedSidebarMenusByCode(code);
    }
  }
}

const startMove = (dom: HTMLElement) => {
  const target = document.querySelector('.tabbar-transition')!;
  const { width , left } = target.getBoundingClientRect(); 
  const minOffset = left;
  const maxOffset = width + left;
  const rect = dom.getBoundingClientRect();
  const domMinOffset = rect.left;
  const domMaxOffset = rect.left + rect.width;
  if (domMinOffset > minOffset && domMaxOffset < maxOffset) {
    return;
  }
  if (domMinOffset < minOffset) {
    const offset = minOffset - domMinOffset;
    moveX(target.scrollLeft - offset);
  } else {
    const offset = domMaxOffset - maxOffset;
    moveX(target.scrollLeft + offset);
  }
}
const moveX = (offset: number) => {
  const target = document.querySelector('.tabbar-transition')!;
  target.scrollTo({
    left : offset,
    behavior : 'smooth'
  })
}
const onCloseTab = (tab: RouteLocationNormalized) => {
  closeAndOpenNextTab(tab);
}
const onUpdate = (evt: SortableEvent) => {
  const oldIndex = evt.oldIndex!;
  const newIndex = evt.newIndex!;
  updateTab(oldIndex , newIndex);
}
const onMaxScreen = () => {
  emits('toggle-fullscreen' , !isFullscreen.value);
}
const onReload = () => {
  emits('reload');
}
const onFixed = () => {
  const tab = currentTabs.value.find(tab => tab.fullPath === route.fullPath);
  updateTabMeta(route.fullPath , {
    fixed : !tab?.meta.fixed
  })
}
const onMouseWheel = (evt: WheelEvent) => {
  const dom = document.querySelector('.tabbar-transition');
  if (dom) {
    dom.scrollTo({
      left : -evt.deltaY + dom.scrollLeft,
      behavior : 'auto'
    });
  }
}
watch(() => route.path , () => {
  nextTick(() => {
    const dom = document.querySelector('.tabbar-item.active') as HTMLElement;
    startMove(dom);
  })
} , {
  immediate : true
});
const onClickLeft = () => {
  const dom = document.querySelector('.tabbar-transition')!;
  const scrollLeft = dom.scrollLeft;
  if (scrollLeft - tabbarWidth > 0) {
    moveX(scrollLeft - tabbarWidth);
  } else {
    moveX(0);
  }
}
const onClickRight = () => {
  const dom = document.querySelector('.tabbar-transition')!;
  const scrollLeft = dom.scrollLeft;
  moveX(tabbarWidth + scrollLeft);
}
onMounted(() => {
  const dom = document.querySelector('.tabbar-transition')!;
  tabbarWidth = dom.getBoundingClientRect().width;
});
</script>
<style lang='less' scoped>
.layout-tabbar {
  width: 100%;
  height: 0.38rem;
  border-bottom: 0.01rem solid;
  transition: all 0.3s cubic-bezier(0.645, 0.045, 0.355, 1);
  .useTheme({
    border-color: border-color;
  });
  .layout-tabbar-inner {
    display: flex;
    align-items: center;
    height: 100%;
    width: 100%;
    .arrow-left-icon-button {
      width: 0.38rem;
      height: 100%;
      display: flex;
      align-items: center;
      justify-content: center;
      border-right: 0.01rem solid;
      cursor: pointer;
      transition: all 0.3s;
      .useTheme({
        border-right-color: border-color;
      });
      .useHover({
        background-color: primary-color;
      } , 0.2);
      .arrow-icon {
        font-size: var(--font-size-base);
        .useTheme({
          color: text-color;
        });
      }
    }
    .arrow-right-icon-button {
      width: 0.38rem;
      height: 100%;
      display: flex;
      align-items: center;
      justify-content: center;
      border-left: 0.01rem solid;
      cursor: pointer;
      transition: all 0.3s;
      .useTheme({
        color: text-color;
      });
      .useTheme({
        border-left-color: border-color;
      });
      .useHover({
        background-color: primary-color;
      } , 0.2);
      .arrow-icon {
        font-size: var(--font-size-base);
        .useTheme({
          color: text-color;
        });
      }
      .fullscreen-icon {
        font-size: var(--font-size-base);
        .useTheme({
          color: text-color;
        });
      }
    }
    .tabbar-box {
      flex: 1;
      height: 100%;
      display: flex;
      position: relative;
      overflow: hidden;
      align-items: center;
      .draggable-box {
        height: 100%;
        width: 100%;
      }
      .tabbar-transition {
        display: flex;
        height: 100%;
        width: 100%;
        overflow: hidden;
        overflow-x: scroll;
        scrollbar-width: none;
        align-items: center;
      }
      .slide-enter-active , .slide-leave-active {
        transition: all 0.3s;
      }
      .slide-enter-from , .slide-leave-to {
        opacity: 0;
        transform: translateX(16px);
      }
      .slide-leave-active {
        position: absolute;
      }
      .tabbar-item {
        height: 100%;
        align-items: center;
        display: flex;
        padding: 0 0.12rem;
        border-right: 0.01rem solid;
        gap: 0.1rem;
        transition: all 0.3s;
        cursor: pointer;
        user-select: none;
        white-space: nowrap;
        .useTheme({
          color: text-color;
        });
        &.card {
          height: 80%;
          border: 0.01rem solid;
          margin: 0 0.04rem;
          border-radius: var(--radius);
          .useTheme({
            border-color: border-color;
          });
          &:first-child {
            margin-left: 0.08rem;
          }
          &:last-child {
            margin-right: 0.08rem;
          }
        }
        &.active {
          .useTheme({
            background-color: primary-color;
          } , 0.3);
          .useTheme({
            color: primary-color;
          });
        }
        &:not(.active):hover {
          .useTheme({
            background-color: primary-color;
          } , 0.2);
        }
        .useTheme({
          border-right-color: border-color;
        });
        .tabbar-icon {
          width: 0.16rem;
          height: 0.16rem;
          object-fit: cover;
        }
        .tabbar-close-icon {
          font-size: var(--font-size-small);
        }
      }
    }
  }
}
</style>